#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>



static int chrdev_open(struct inode *inode, struct file *file)
{
	printk(KERN_EMERG "This is chrdev_open \n");
	return 0;
}

static ssize_t chrdev_read(struct file *file,char __user *buf, size_t size, loff_t *off)
{
	printk(KERN_EMERG "This is chrdev_read \n");
	return 0;
}

static ssize_t chrdev_write(struct file *file,const char __user *buf,size_t size,loff_t *off)
{
	printk(KERN_EMERG "This is chrdev_write \n");
	return 0;
}

static int chrdev_release(struct inode *inode, struct file *file)
{
	return 0;
}


static dev_t dev_num;

struct cdev cdev_test;

struct file_operations chrdev_fops_test = { 
	.owner		= THIS_MODULE,
	.open		= chrdev_open,
	.read		= chrdev_read,
	.write		= chrdev_write,
	.release	= chrdev_release,
};

struct class *class_test;

static int chrdev_fops_init(void)
{
    int ret = 0;
    int major,minor;

    printk(KERN_EMERG "chrdev_fops_init\r\n");

  
    ret = alloc_chrdev_region(&dev_num, 0, 1, "chrdev_name");
    if(ret<0)
    {
        printk(KERN_EMERG "alloc_chrdev_region is error \r\n");
    }
    printk(KERN_EMERG "alloc_chrdev_region is ok \r\n");

    major = MAJOR(dev_num);
    minor = MINOR(dev_num);
    printk(KERN_EMERG "major is %d\r\n minor is %d \r\n", major, minor);

    cdev_init(&cdev_test, &chrdev_fops_test);
    cdev_test.owner = THIS_MODULE;
    cdev_add(&cdev_test, dev_num, 1);
    if(ret<0)
    {
        printk(KERN_EMERG "cdev_add is error \r\n");
    }
    printk(KERN_EMERG "cdev_add is ok \r\n");

    class_test = class_create(THIS_MODULE, "class_test");
    device_create(class_test, NULL, dev_num, NULL, "device_test");
    
    return 0;
}

static void chrdev_fops_exit(void)
{
    cdev_del(&cdev_test);
    unregister_chrdev_region(dev_num, 1);//释放字符设备所申请的设备号
    device_destroy(class_test, dev_num);// 删除创建的设备
    class_destroy(class_test);
    printk(KERN_EMERG "chrdev_fops_exit\r\n");
}

module_init(chrdev_fops_init);
module_exit(chrdev_fops_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("jianghe");
